Source code for /engineering/webperf/slave-v4[j1.2]/Dispatcher.javaOriginal file Dispatcher.java
   1 import java.util.*;
   2 
   3 public class Dispatcher extends Thread {
   4    
   5    public final static int		statusNEW 	= 0;
   6    public final static int		statusWAIT  = 1;
   7    public final static int		statusRUN   = 2;
   8    public final static int 		statusPAUSE	= 3;
   9    public final static int 		statusSTOP	= 4;
  10    public final static int		statusDIE	= 9;
  11    public int currentStatus = statusNEW;
  12 
  13    public final static String		wordError = "!ERROR!";
  14    public final static String		wordSucc  = "SUCCESS";
  15 
  16    public final static String		userName    = "bob";	// Temp hack
  17 										// Defines text for username/pass	
  18 
  19    CmdQueue		commandsRx;
  20    Command		currentCommand;
  21 
  22    SlaveUI		myUI;
  23    
  24    String		target;
  25    Logging		log;
  26 
  27    String		currentScript;
  28    Scripter		script;
  29    ScriptItem	sItem;
  30    int 		scriptStep;
  31 
  32    Stack		loopStack;
  33    int		loopItem;
  34    Integer		loopTemp;
  35    
  36    // Chutes
  37    HTTPOut[]	out;
  38    ReqQueue[]	chute;	
  39    int 		chuteCount = 4;
  40    int		useChute;
  41 
  42    // Users
  43    int		userCount;
  44    int		userStart;
  45 
  46    int		index;
  47 				 
  48    boolean		timeWaitOn = false;
  49    long		waitTill;
  50    public final static int 	CLOCK_MULTI	 = 1000;
  51  
  52    boolean		syncOn = false;
  53 
  54 
  55    // helper threads
  56    public HTTPIn		masterRx;
  57 
  58    public Dispatcher(SlaveUI ui) {
  59 	
  60 	// initialize me
  61       myUI = ui;
  62 	this.initialize();
  63 	timeWaitOn = false;
  64 	loopStack  = new Stack();
  65    }
  66 
  67    public void run() {
  68       
  69 	myUI.putScreenLog("Dispatcher: Im up.");
  70 
  71       masterRx.start();
  72 
  73 	// Dispatch loop
  74 	while (currentStatus != statusDIE) {
  75 
  76 	   // check command queue
  77 	   if (commandsRx.isCommand()) {
  78 		currentCommand = commandsRx.getCommand();
  79 
  80 		// process command
  81 		switch(currentCommand.getCommand()) {
  82 		   case Command.cmdNULL:
  83 			handleNull();			
  84 			break;
  85 
  86 		   case Command.cmdSTOP:
  87 			handleStop();
  88 			break;
  89 
  90 		   case Command.cmdNEW:
  91 			handleNew();
  92 			break;
  93 
  94 		   case Command.cmdPAUSE:
  95 			handlePause();
  96 			break;
  97 
  98 		   case Command.cmdTARGET:
  99 			handleTarget();	
 100 			break;
 101 		 
 102 		   case Command.cmdGETLOG:
 103 			handleGetLog();
 104 			break;   
 105 
 106 		   case Command.cmdGO:
 107 			handleGo();
 108 			break;   
 109 
 110 		   case Command.cmdPING:
 111 			handlePing();
 112 			break;   
 113 
 114 		   default:
 115 			myUI.putScreenLog("Software detected fault Dispatch.run");
 116 			log.post("Software detected fault Dispatch.run");
 117 			break;
 118 		}
 119          } // end if
 120 
 121 	   if (currentStatus == statusRUN) {
 122 
 123 	      if (timeWaitOn == true) {
 124 
 125 			// see if timer expired
 126 			if (log.getTiming() >= waitTill) timeWaitOn = false;
 127 
 128 		} else {
 129 
 130 			if (syncOn == true) {
 131 			   // See if we can clear a sync
 132 			   handleSync();
 133 
 134 			} else {
 135 		 	   // lets grab a script item, if we have any more
 136 			   if (scriptStep < script.numberItems) {	
 137 			   	handleScript();
 138 			   } else {
 139 				//the script is done.
 140 				//log and change state.  (We will want some kind of sync here)
 141 				log.post("DONE!!! Ending at "+log.getTiming());
 142 				myUI.putScreenLog("!!! DONE.  Script has ended.");
 143 				currentStatus = statusSTOP;
 144 			   }
 145 			}
 146 
 147 		}
 148 
 149 		// take a breather.  I may want to remove this.  But, it should keep this damned 
 150 		// thread from sucking up soooo much CPU time when relatively idle.
 151 		try {
 152 		   this.sleep(100);
 153 		} catch (Exception e) { };
 154 
 155 	   }  else {
 156 
 157 		// Idle this thread if nothing is in the command queue and nothing is running
 158 		if (commandsRx.isCommand() == false) {
 159 		   try {
 160 			this.sleep(500);
 161 		   } catch (InterruptedException e) {
 162 		      // dont care
 163 		   }
 164 		} 
 165 	   } // end if running
 166 
 167       } // end while
 168 
 169    }
 170 
 171    protected boolean initialize() {
 172       
 173 	// Build helpers
 174 	commandsRx = new CmdQueue(); 
 175 
 176 	log  	     = new Logging();
 177 
 178 	masterRx = new HTTPIn(true, commandsRx);  
 179   
 180 	return true;
 181    }
 182 
 183    protected void handleNew() {
 184 	String r;
 185 	String i;
 186 
 187 	log.post("RX: NEW Command");
 188 	myUI.putScreenLog("RX: NEW Command");
 189 
 190 	// Check against current state
 191 	switch (currentStatus) {
 192 	
 193 	   case statusSTOP:
 194 	   case statusNEW:
 195 		script = new Scripter();
 196 		i 	 = script.load(currentCommand.getStringParam());
 197 	
 198 		if (script.errors > 0) {
 199 	  	   myUI.putScreenLog("!!! A NEW command REJECTED due to errors.");
 200 		   myUI.putScreenLog("!!! >>> Processed.  "+script.errors+" errors found.");
 201 	    	   r = formResponse(wordError, "NEW script has been rejected by slave.", i);
 202 		   currentCommand.respond(r);
 203 	 	   log.post("--> NEW Parse errors: " + script.errors);
 204 		   break;
 205 		}
 206 
 207 		userStart  = currentCommand.getIntParam();
 208 		chuteCount = script.chutes;
 209 		userCount  = script.users;
 210 		useChute   = 0;
 211 
 212 		// report 
 213 		log.clear();				// Clear the log here.	
 214  		currentScript = script.name;
 215 		myUI.setScriptName(currentScript);  
 216 		myUI.putScreenLog("!!! A NEW command accepted.");
 217 		r = formResponse(wordSucc, "NEW script has been loaded on slave.", i);
 218 		currentCommand.respond(r);
 219 
 220 		log.post("--> NEW Script Name: " + currentScript);
 221 		currentStatus = statusWAIT;
 222 
 223 		break;		
 224 
 225 	   default:
 226 		myUI.putScreenLog("!!! >>> Rejecting NEW.  Script already running or pending.");
 227 	   	r = formResponse(wordError, "Rejecting NEW.  Already running or pending",
 228 		    "You must STOP the currently running/pending script before posting a NEW script\n");
 229 	   	currentCommand.respond(r);
 230 	  	log.post("--> NEW Rejected.");
 231 
 232 	}
 233    }
 234 
 235    protected void handleStop() {
 236 	String r;
 237 
 238 	log.post("RX: STOP Command");
 239 	myUI.putScreenLog("RX: STOP Command");
 240 
 241 	// Check against current state
 242 	switch (currentStatus) {
 243 	
 244 	   case statusWAIT:
 245 	   case statusRUN:
 246 	   case statusPAUSE:
 247 
 248 		myUI.putScreenLog("!!! A STOP command received.  Script stopped.");
 249 		r = formResponse(wordSucc, "Current script stopped.", 
 250 					"The script has been stopped on the slave.");
 251 		currentCommand.respond(r);	
 252 		log.post("--> Script has been stopped.");
 253 
 254 		currentStatus = statusSTOP;
 255 		log.stopTiming();
 256 		log.done();
 257 
 258 		// Kill the chutes
 259 		int i = 0;
 260 		while (i < chuteCount) {
 261 		   try {
 262 		      out[i].stop();
 263 		   } catch (Exception e) {
 264 			// dont care
 265 		   }
 266 		   i++;
 267  		}	
 268 		break;
 269 
 270 	   default:
 271 		myUI.putScreenLog("!!! >>> Rejecting STOP.  Script not running or pending.");
 272 	   	r = formResponse(wordError, "Rejecting STOP.  Not running or pending",
 273 		    "There is no script currently running or pending.\n");
 274 	   	currentCommand.respond(r);
 275 	  	log.post("--> STOP Rejected.");
 276 	}
 277    }
 278 
 279    protected void handleNull() {
 280 	String r;
 281 	String i;
 282 
 283 	myUI.putScreenLog("RX: >> NULL << Command");
 284 	log.post("RX: >> NULL << Command");
 285 	log.post("--> Ignored.");
 286 
 287 	// report 
 288 	myUI.putScreenLog("!!! Ingoring NULL.");
 289 	r = formResponse(wordError, "Unrecognized command", 
 290 				"I dont know what to do with that command.");
 291 	currentCommand.respond(r);
 292    }
 293 
 294    protected void handleTarget() {
 295 	String r;
 296 
 297 	log.post("RX: TARGET Command");
 298 	myUI.putScreenLog("RX: TARGET Command");
 299 
 300 	// Check against current state
 301 	switch (currentStatus) {
 302 	
 303 	   case statusSTOP:
 304 	   case statusNEW:
 305 
 306 		target = currentCommand.getStringParam();
 307 		myUI.setTarget(target);
 308 
 309 		// report 
 310 		myUI.putScreenLog("!!! TARGET accepted for :"+target);
 311 		log.post("--> Target accepted for :"+target);
 312 		r = formResponse(wordSucc, "TARGET Accepted", 
 313 				     "New target is now set for this slave.");
 314 		currentCommand.respond(r);
 315 		break;
 316 
 317 	   default:
 318 		myUI.putScreenLog("!!! >>> Rejecting TARGET.  Script is running or pending.");
 319 	   	r = formResponse(wordError, "Rejecting TARGET.  Script running or pending",
 320 		    "You cannot set a target while a script is running or pending.\n");
 321 	   	currentCommand.respond(r);
 322 	  	log.post("--> TARGET Rejected.");
 323 	}
 324    }
 325 
 326    protected void handleGetLog() {
 327 	String r;
 328 
 329 	myUI.putScreenLog("RX: GETLOG Command");
 330 	log.post("RX: GETLOG Command");
 331 
 332 	// report 
 333 	myUI.putScreenLog("!!! Log posted to master.");
 334 
 335 	r = formResponse(wordSucc, "Current LOG", log.getLog());
 336 	currentCommand.respond(r);
 337    }
 338 
 339    protected void handlePing() {
 340 	String r;
 341 
 342 	myUI.putScreenLog("RX: PING Command");
 343 	//log.post("RX: PING Command");
 344 
 345 	// report 
 346 	r = formResponse(wordSucc, "PONG", "Status=" + currentStatus + "=");
 347 	currentCommand.respond(r);
 348    }
 349 
 350 
 351    protected void handleGo() {
 352 	String r;
 353 
 354 	myUI.putScreenLog("RX: GO command");
 355 
 356 	// Check against current state
 357 	switch (currentStatus) {
 358 	
 359 	   case statusWAIT:
 360 	   case statusSTOP:
 361 		myUI.putScreenLog("!!! A GO command received.  Script running.");
 362 		r = formResponse(wordSucc, "Current script running.", 
 363 					"The script is now running from the start.");
 364 		currentCommand.respond(r);
 365 		log.clear();	
 366 		log.startTiming();
 367 		log.post("RX: GO Command");
 368 		log.post("--> Script has been started.");
 369 		
 370 		// Build the chutes
 371 		int i = 0;
 372 		chute = new ReqQueue[chuteCount];
 373 		out	= new HTTPOut[chuteCount];
 374 		while (i < chuteCount) {
 375 		   chute[i] = new ReqQueue();
 376 		   chute[i].init();
 377 		   out[i] = new HTTPOut();
 378                out[i].init(chute[i], log);
 379 		   out[i].start();
 380 		   i++;
 381  		}	
 382 		useChute = 0;	
 383 
 384 		currentStatus = statusRUN;
 385 
 386 		// Start from beginning of script!
 387 		scriptStep	  = 0;			
 388 		while(loopStack.empty() != true) { loopTemp = (Integer) loopStack.pop(); }
 389 		loopItem = ScriptItem.maxLoop;		// remove any pending loops
 390 
 391 		break;
 392 
 393 	   case statusPAUSE:
 394 
 395 		myUI.putScreenLog("!!! A GO command received.  Script restarted from PAUSE.");
 396 		r = formResponse(wordSucc, "Current script restarted.", 
 397 					"The script is now running from a pause.");
 398 		currentCommand.respond(r);
 399 		log.resumeTiming();
 400 		log.post("RX: GO Command");
 401 		log.post("--> Script has been restarted from a pause.");
 402 
 403 		currentStatus = statusRUN;
 404 		break;
 405 
 406 	   default:
 407 		//log.post("RX: GO Command");
 408 		myUI.putScreenLog("!!! >>> Rejecting GO.  Script not ready or already running.");
 409 	   	r = formResponse(wordError, "Rejecting GO.  Already running or not ready.",
 410 		    "A script is already running or one has not been loaded.\n");
 411 	   	currentCommand.respond(r);
 412 	  	log.post("--> GO Rejected.");
 413 	}
 414    }
 415 
 416    protected void handlePause() {
 417 	String r;
 418 
 419 	myUI.putScreenLog("RX: PAUSE Command");
 420 	log.post("RX: PAUSE Command");
 421 
 422 	// Check command against state
 423 	if (currentStatus != statusRUN) {
 424 	   myUI.putScreenLog("!!! >>> Rejecting PAUSE.  Not currently running.");
 425 	   r = formResponse(wordError, "Rejecting PAUSE.",
 426 		 "No script is currently running.\n");
 427 	   currentCommand.respond(r);
 428 	   log.post("--> PAUSE Rejected.  Not running.");
 429 	   return;
 430 	}
 431 
 432 	currentStatus = statusWAIT;
 433 	log.pauseTiming();
 434 
 435 	// report 
 436 	myUI.putScreenLog("!!! PAUSE accepted. ");
 437 	log.post("--> PAUSE Accepted:");
 438 	r = formResponse(wordSucc, "PAUSE Accepted", "Script is now paused.");
 439 	currentCommand.respond(r);
 440    }
 441 
 442    private String formResponse(String  title, String  note, String  content) {
 443       StringBuffer r = new StringBuffer();
 444 	r.append("<HTML><HEAD><TITLE>"+title+"</TITLE></HEAD><BODY><H2>"+note);
 445 	r.append("</H2><PRE>"+content+"</PRE></BODY></HTML>");
 446 	return r.toString();
 447    }
 448 
 449    private void handleScript() {
 450 
 451 	sItem = script.getItem(scriptStep);
 452 	scriptStep++;
 453 	//System.out.println("TOKEN: " + sItem.token); 
 454 	switch(sItem.token) {
 455 
 456 	   case ScriptItem.tokenPut:
 457 		int    i;
 458 		if (sItem.id == 0) {
 459 		   i = useChute;
 460 		   useChute++;
 461 		   if (useChute >= chuteCount) useChute = 0;	
 462 		} else {
 463 		   i = (script.userList[sItem.id]);
 464 		}
 465 		put( sItem.text, sItem.id, i );
 466 		break;
 467 
 468 	   case ScriptItem.tokenIndexPut:
 469 		if (index > userCount) {
 470 		   myUI.putScreenLog("Software detected fault Dispatch.handleScript-INDEX out of bounds");
 471 		   log.post("Software detected fault Dispatch.handleScript-INDEX Inc of bounds.  Used index = 1");
 472 		   index = 1;
 473 		}
 474 		try {   
 475 		   put( sItem.text, index, script.userList[index] );
 476 		} catch (Exception e) {
 477 		   System.out.println("INDEX OOB =  " + index);
 478 		   myUI.putScreenLog("Software detected fault Dispatch.handleScript-INDEX out of bounds");
 479 		   log.post("Software detected fault Dispatch.handleScript-INDEX out of bounds");
 480 		}
 481 		break;
 482 
 483 	   case ScriptItem.tokenIndexWait:
 484 		if (index > userCount) {
 485 		   myUI.putScreenLog("Software detected fault Dispatch.handleScript-INDEX WAIT out of bounds");
 486 		   log.post("Software detected fault Dispatch.handleScript-INDEX WAIT of bounds.  Used index = 1");
 487 		   index = 1;
 488 		}
 489 		try {
 490 		   chuteWait(index, (sItem.count * CLOCK_MULTI));
 491 		} catch (Exception e) {
 492 		   System.out.println("INDEX WAIT OOB =  " + index);
 493 		   myUI.putScreenLog("Software detected fault Dispatch.handleScript-INDEX WAIT out of bounds");
 494 		   log.post("Software detected fault Dispatch.handleScript-INDEX WAIT out of bounds");
 495 		}
 496 		break;
 497 		
 498 	   case ScriptItem.tokenWait:
 499 		if (sItem.id == 0) {
 500 		   // General Wait
 501 		   timeWaitOn = true;
 502 		   log.post("WAIT : Time now : "+log.getTiming());
 503    		   waitTill = log.getTiming() + (sItem.count * CLOCK_MULTI);
 504 		   log.post("     : until "+waitTill);
 505 		} else {
 506 		   // Chute wait.  Follows a user
 507 		   chuteWait(sItem.id, (sItem.count * CLOCK_MULTI));
 508 		}
 509 		break;
 510 
 511 	   case ScriptItem.tokenLoop:
 512 		
 513 		// If we have any loops pending, push the loopItem onto a stack so
 514 		// we can remember the loop count later.
 515 		if (loopItem != ScriptItem.maxLoop) {
 516 		   loopTemp = new Integer(loopItem);	
 517 		   loopStack.push(loopTemp);
 518 		}
 519 		loopItem  = sItem.count;
 520 		break;
 521 		
 522 	   case ScriptItem.tokenEndLoop:
 523 		
 524 		loopItem--;
 525 		if (loopItem > 0) {
 526 			scriptStep = sItem.count + 1;
 527 
 528 		} else { 
 529 			// Do we need to recover a outside loop?
 530 			if (loopStack.empty() == false) {
 531 			   loopTemp  = (Integer) loopStack.pop();
 532 			   loopItem  = loopTemp.intValue(); 
 533 
 534 			} else {
 535 			   loopItem = ScriptItem.maxLoop;	// clear the pending loop (or, adding a new
 536 									// loop will be nested.)
 537 			}
 538 		}
 539 		break;
 540 
 541 	   case ScriptItem.tokenEnd:
 542 		log.post("END : Ending at "+log.getTiming());
 543 		break;
 544 
 545 	   case ScriptItem.tokenSync:
 546 		log.post("SYNC: Starting at "+log.getTiming());
 547 		syncOn = true;
 548 		break;
 549 
 550 	   case ScriptItem.tokenIndexSet:
 551 		index = sItem.count;
 552 		System.out.println("INDEX =  " + index);
 553 		break;
 554 
 555 	   case ScriptItem.tokenIndexInc:
 556 		index++;
 557 		break;
 558 
 559 	   case ScriptItem.tokenName:
 560 	   default:
 561 		myUI.putScreenLog("Software detected fault Dispatch.handleScript-tokenDEFAULT");
 562 		log.post("Software detected fault Dispatch.handleScript-tokenDEFAULT");
 563 		break;
 564 
 565 	}
 566 
 567    }
 568       
 569    private void handleSync() {
 570 
 571 	int 		i	    = 0;
 572 	int 		size	    = 0;
 573 	int		idleClear = 0;
 574 
 575 	while (i < chuteCount) {
 576   	   size = size + chute[i].size();
 577   	   if (out[i].idle == false) idleClear++;
 578 	   i++;
 579  	}	
 580 	if ((size == 0)&&(idleClear == 0)) {
 581 	   log.post("SYNC:  Sync cleared.");
 582 	   syncOn = false;	
 583 	}
 584 
 585    }
 586 
 587    private void put(String  text, int  user, int  chuteNum) {
 588 	StringBuffer s = new StringBuffer();
 589 	Request	 r = new Request();
 590 	int		 c = chuteNum - 1;    // The chute is one less as an array index;
 591 	int		 rover = 0;
 592 	int		 size  = text.length();
 593 	char		 temp;
 594 
 595 	// Lets chug through this dog and build the URL.  Replace any idChar with 
 596 	// a username/password string.
 597 	s.append("http://"+target);
 598 	while (rover < size) {
 599 	   temp = text.charAt(rover);
 600 	   if (temp == ScriptItem.idChar) {
 601 		s.append(userName + ((user-1)+userStart));
 602 	   } else {
 603 	      s.append(temp);
 604 	   }
 605 	   rover++;	
 606 	}
 607 
 608 	r.type = Request.reqPUT;
 609 	r.text = s.toString();
 610 
 611 //System.out.println("QUEUE " + c + ": PUT : " + r.text); 
 612 //System.out.println("QUEUE " + c + ": PUT : " + text); 
 613 	chute[c].put(r);
 614    }
 615 
 616    private void chuteWait(int  user, int  time) {
 617 	Request	 r = new Request();
 618 	int		 c;
 619 
 620 	c 		= script.userList[user]-1; // The chute is one less as an array index;
 621 	r.type 	= Request.reqWAIT;
 622 	r.intParam	= time;
 623 
 624 	System.out.println("QUEUE " + c + ": WAIT " + time); 
 625 	chute[c].put(r);
 626    }
 627 
 628 
 629 }     
 630